#!/usr/bin/env bash
#-------------------------------------------------------
#	FileName	: 可交互目录树.sh
#	Author		：hpy
#	Date		：2020年11月08日
#	Description	：该脚本需要配合conf.ini文件使用，根据ini文件
#   不同的配置可以实现显示不同后缀的文件，并且可以配置执行文件的简
#   单命令！ini文件配置实例
#+++++++++++++++++++ conf.ini 文件内容 +++++++++++++++++++++
#[tree] #配置终端目录树脚本显示的文件类型
#    FileType = sh fish   # 配置过滤的文件 . : 显示所有文件  sh: 显示.sh文件 fish：显示 .fish文件
#    Title = 可用Shell脚本
#    Exec = eval  # 执行脚本的命令或者应用程序 cat:显示文件内容 eval 执行脚本
#    TermName = Shell #终端名称 将会显示在运行界面
#------------------------------------------------------- 

cd $(dirname $0)

#############################################################
#函数 ReadIni_pro 
#读取ini文件
#参数1：ini文件
#参数2：Section
#参数3：option / key
#当找到匹配的key时，返回状态码：0，并 echo 结果 ，否则返回状态码 ：2 
#该版本会自动过滤注释，查找时不会超过 section 段
function ReadIni_pro(){
    iniFile=$1 && Section=$2 && Key=$3 
    startLine=$(grep -n "\[$Section\]" $iniFile | cut -d ':' -f1)
    test ${#startLine} -eq  0 && return 2
    endLine=$(cat $iniFile | tail -n +$startLine | grep -n "\[*\]" | sed -n '2p' | cut -d ':' -f1)
    test ${#endLine} -eq 0 && endLine=$(cat $iniFile | wc -l)
    var=$(tail -n +$startLine $iniFile|head -$endLine|\
    awk -F '=' '/\['$Section'\]/{a=1}a==1&&$1~/'$Key'/{print $2;exit}')
    var=$(echo $var | cut -d'#' -f1)  #去除 # 注释部分
    var=$(echo $var | cut -d';' -f1)  #去除 ； 注释部分
    test ${#var} -gt  0 && echo $var  || return 2 #找到值就echo 否则返回代码 1 
}
#相对路径宏
DIS_FILE="$(pwd)/.dis_search.txt"
DIS_FILE_REAL="$(pwd)/.dis.txt"
LOCAL_PATH="$(pwd)/"

flagFile=".sortdir"
# 读取ini配置文件
FILE_TYPE="sh fish"
TITLE_NAME="标题"
EXEC="cat"
TERM_NAME=""
if [ -f conf.ini ] ;then
    #解析文件类型
    FILE_TYPE=$(ReadIni_pro conf.ini tree FileType)
	test ${#FILE_TYPE} -eq 0 && FILE_TYPE="sh fish"
    #解析标题
    TITLE_NAME=$(ReadIni_pro conf.ini tree Title)
	test ${#TITLE_NAME} -eq 0 && FILE_TYPE="标题"
    #解析执行程序
    EXEC=$(ReadIni_pro conf.ini tree Exec)
	test ${#EXEC} -eq 0 && EXEC="eval"
    #解析终端显示名称
    TERM_NAME=$(ReadIni_pro conf.ini tree TermName)
	test ${#TERM_NAME} -eq 0 && TERM_NAME=""
fi
#根据配置文件找出文件类型
function isFile(){
    if [[ $FILE_TYPE == "." ]] ; then
        echo "0"
        return
    fi
    for it in $FILE_TYPE
    do
        if [[ "$1" == "$it" ]] ; then
            echo "0"
            return 
        fi
    done
    echo "1"
}



#全局变量
key=null
curl=0
treeCnt=0
Max=30
openPosi=100
exeFile=""

function main() {
	#初始化，保证每次只打开一级目录显示
    local adir=$(find -type f -name ".sortdir")
    echo "0" > $flagFile
    if [ ${#adir} -gt 0 ] ; then
        for sfile in $adir
        do
            echo "0" > $sfile
        done
    fi
	echo "1" > $flagFile
    cat /dev/null > $DIS_FILE_REAL
    disTree ./ ./ "" > $DIS_FILE
    #sed -e "s:${LOCAL_PATH}::g" $DIS_FILE > $DIS_FILE_REAL
    Max=$treeCnt
    while :
    do
        clear
        treeCnt=0
        openPosi=100
        if [[ $key == "right" ]] ;then
            cd $LOCAL_PATH
            cat /dev/null > $DIS_FILE_REAL
            disTree ./ ./ "" > $DIS_FILE
            Max=$treeCnt
            #sed -e "s:${LOCAL_PATH}::g" $DIS_FILE > $DIS_FILE_REAL
        fi 
        #disTree ./ ./ ""
        disAnsTree #显示
        read -sn1 key
        #输入按键检测
        in_buf[0]=${in_buf[1]}
        in_buf[1]=${in_buf[2]}
        in_buf[2]=$key
        key=$(check_key ${in_buf[0]} ${in_buf[1]} ${in_buf[2]})
        if [[ $key == "up" ]];then
            if [ $curl -gt 0 ];then
                curl=$[curl-1]
            fi
        elif [[ $key == "down" ]] ; then
            curl_tmp=$[curl+1]
            if [ $curl_tmp -ne $Max ] ; then
                curl=$[curl+1]
            fi
        elif  [[ $key == "right" ]] ; then
            if [ $curl -gt 0 ] ; then
                check_right 
            else
                 key="null"
            fi
        fi
    done
}

# 方向右键检测到的操作
function check_right() {
    local lin=$[curl+1]
    local var=$(sed -n "${lin}p" $DIS_FILE)
    var=${var#*/}
    var="/$var"
    if [ -d $var ] ; then 
        cd $var 
        local flag=$(cat $flagFile)
        if [ $flag -eq 0 ] ;then
            echo "1" > $flagFile
        else
            local adir=$(find -type f -name ".sortdir")
            echo "0" > $flagFile
            if [ ${#adir} -q 0 ] ; then
                return 
            fi
            for sfile in $adir
            do
                echo "0" > $sfile
            done
            #echo "0" > $flagFile
        fi
        cd $LOCAL_PATH
        return
    fi 

    if [ -f "$var" ]; then 
        echo "------------- $TERM_NAME console -------------"
        local cmd="$EXEC $var"
        eval $cmd
        echo
        echo "按任意键继续....."
        read -n1 in
        cd $LOCAL_PATH
        return
    fi 
}

# 列出当前目录下所有目录
function listDir(){
    ls -d */
}
#显示 打印
function my_echo(){
    echo -e "|$*"
    return 
    if [ $curl -eq $treeCnt ] ;then
        echo -e "|\033[47;30m$*\033[0m"
    else
        echo -e "|$*"
    fi
}



#从文件读取显示，加快刷新速度
function disAnsTree(){
    echo "------- $TITLE_NAME -------"
    local idx=0
    while read line
    do
        if [ $idx -eq 0 ] ;then
            line="| - ./"
        fi 
        if [ $curl -eq $idx ] ;then
            echo -e "\033[47;30m$line\033[0m"
        else
            echo  "$line"
        fi
        idx=$[idx+1]
        
    done < $DIS_FILE_REAL
}

#目录树形式显示文件结构 
#输入参数为方向按键解析值 up down left right 和 enter
function listDirTree(){
    #dirInNoePath=$(ls -d */) #获得当前目录下的一级目录
    cnt=0
    local curl=$1  #光标位置
    while [ $cnt -lt $Max ] 
    do
        if [ $curl -eq $cnt ];then
            echo_wb "- 条目$cnt"
        else
            echo_bw "- 条目$cnt"
        fi
        cnt=$[cnt+1]
    done
    echo ------------ 
}



# 方向键检测
# 检测到方向键打印 up down left right ，否则默认检测到 enter
# 参数1：2次打拍的按键输入
# 参数2：1次打拍的按键输入
# 参数3：按键输入
function check_key(){
    inputs[0]=$1
    inputs[1]=$2
    inputs[2]=$3
    if [[ ${inputs[1]} == "[" ]];then
        if [[ ${inputs[2]} == "A" ]];then
            echo "up"
        elif [[ ${inputs[2]} == "B" ]] ;then
            echo "down"
        elif [[ ${inputs[2]} == "C" ]] ;then
            echo "right"
        elif [[ ${inputs[2]} == "D" ]] ;then
            echo "left"
        fi
   # else 
    #    echo "enter"
    fi
}

#列出目录
findDir(){
    l1=$(ls)
    for i in $l1
    do
        test -d $i && echo "$i"
    done
}

#寻找和要求的文件
findFile(){
    l1=$(ls)
    for i in $l1
    do
        test ! -f $i && continue
        local typeFile=${i##*.}
        local ans=$(isFile "$typeFile")
        if [ $ans -eq 0 ] ;then
            echo $i
        fi
    done
}

#显示文件树
disTree(){
    local rootDir=$1
    local dstDir=$2 
    local format=$3
    local isOpen=0;
    
    test -d $dstDir && cd $dstDir || return
    local nowPathDir=$(findDir)
    local nowPathFile=$(findFile)
    local numOfDir=$(findDir| wc -l) #可见文件夹数量
    local numOfFile=$(findFile| wc -l) #文件夹数量
    if [ ! -f $flagFile ] ;then
        echo "0" >  $flagFile
    else
        isOpen=$(cat $flagFile)
    fi

    if [ $isOpen -eq 1 ] ;then #打开目录标志
		my_echo  "$format - $rootDir/$dstDir" 
        my_echo  "$format - $dstDir" >> $DIS_FILE_REAL
		treeCnt=$[treeCnt+1]
        
        if [ $numOfDir -gt 0 ] ;then
            for adir in $nowPathDir
            do
                test ${#adir} -eq 0 && break
                disTree $(pwd) $adir " $format "
            done
        fi
        if [ $numOfFile -gt 0 ] ;then
            for aFile in $nowPathFile
            do
                my_echo "$format     $(pwd)/$aFile"
                my_echo "$format     $aFile" >> $DIS_FILE_REAL 
                treeCnt=$[treeCnt+1]
            done
        fi
        if [ $numOfDir -ge 0 ] ;then 
            cd $rootDir
            return 
        fi
        cd $rootDir
        #return 
    else
		if [ $numOfDir -gt 0 ] || [ $numOfFile -gt 0 ] ;then #不显示空文件夹
			my_echo "$format + $rootDir/$dstDir" 
			my_echo "$format + $dstDir" >> $DIS_FILE_REAL 
			treeCnt=$[treeCnt+1]
		fi 
        cd $rootDir
        return 
    fi
}

main $*